package com.atguigu.gmall.item.controller;

import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RCountDownLatch;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.TimeUnit;

/**
 * @author lfy
 * @Description
 * @create 2023-08-21 15:41
 */
@Slf4j
@RestController
public class RedissonLockController {

    @Autowired
    RedissonClient redissonClient;

    @GetMapping("/longzhu")
    public String longzhu() {

        RCountDownLatch hahalong = redissonClient.getCountDownLatch("hahalong");

        hahalong.countDown();
        return "收集一颗";
    }


    @GetMapping("/shenlong")
    public String zhaohuanshenlong() throws InterruptedException {
        RCountDownLatch latch = redissonClient.getCountDownLatch("hahalong");
        latch.trySetCount(7);

        latch.await();

        return "神龙来了...o.....";
    }


    @GetMapping("/haha/lock")
    public String lock() {
        //1、获取锁
        RLock lock = redissonClient.getLock("lock");


        //2、加锁： 占坑+过期时间
        log.info("开始抢锁...");
        //效果：
        //1、默认锁时间 30s
        //2、锁会自动续期，每隔10s续满期。
        //3、所有的锁操作都是lua脚本，保证原子性
        lock.lock(); //阻塞等锁。锁一拿到默认30s，且有自动续期

//        lock.lock(10,TimeUnit.SECONDS); //强行等锁，一定等到锁，一旦拿到锁以后，把锁的过期时间设置为10s，没有自动续期

//        boolean b = lock.tryLock(); //不用阻塞等锁；锁一拿到默认30s，且有自动续期
//        lock.tryLock(20,10,TimeUnit.SECONDS); //最多等锁20s，20s以内得到锁了，锁的过期时间设为10s，没有自动续期


        try {
            //进行业务操作
            try {
                log.info("抢锁成功...");
                TimeUnit.SECONDS.sleep(60);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

        } finally {
            //3、解锁
            log.info("解锁...");
            try {
                lock.unlock(); //自动会发现到是否解到别人的锁
            } catch (Exception e) {

            }
        }


        return "ok";
    }
}
